package com.gitee.target123.develop.common.redis;

import com.alibaba.fastjson.JSON;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class RedisTemplateUtil {

    private RedisTemplate<String,String> redisTemplate;

    public RedisTemplateUtil(RedisTemplate<String,String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public RedisTemplate<String, String> getRedisTemplate() {
        return this.redisTemplate;
    }

    public ValueOperations<String, String> opsForValue(){
        return this.redisTemplate.opsForValue();
    }

    public HashOperations<String,String,Object> opsForHash(){
        return this.redisTemplate.opsForHash();
    }

    /**
     * 是否存在key
     * @param key
     * @return
     */
    public boolean hasKey(String key){
        Boolean hasKey = this.redisTemplate.hasKey(key);
        return hasKey!=null && hasKey;
    }

    /**
     * 删除key
     * @param key
     * @return
     */
    public boolean delete(String key){
        if (hasKey(key)){
            Boolean delete = this.redisTemplate.delete(key);
            return delete!=null && delete;
        }
        return false;
    }

    /**
     * 设置key-value
     * @param key
     * @param obj
     * @param timeout
     * @param unit
     */
    public void set(String key,Object obj,long timeout, TimeUnit unit){
        ValueOperations<String, String> operations = opsForValue();
        String value;
        if (obj instanceof Integer || obj instanceof Long || obj instanceof Boolean
                || obj instanceof Double || obj instanceof Float){
            value = String.valueOf(obj);
        } else if (obj instanceof String){
            value = (String) obj;
        } else {
            value = JSON.toJSONString(obj);
        }
        operations.set(key, value, timeout, unit);
    }

    /**
     * 设置key-value,if key 不存在
     * @param key
     * @param obj
     * @param timeout
     * @param unit
     * @return
     */
    public boolean setIfAbsent(String key,Object obj,long timeout, TimeUnit unit){
        ValueOperations<String, String> operations = opsForValue();
        String value;
        if (obj instanceof Integer || obj instanceof Long || obj instanceof Boolean
            || obj instanceof Double || obj instanceof Float){
            value = String.valueOf(obj);
        } else if (obj instanceof String){
            value = (String) obj;
        } else {
            value = JSON.toJSONString(obj);
        }
        Boolean ifAbsent = operations.setIfAbsent(key, value, timeout, unit);
        return ifAbsent!=null && ifAbsent;
    }

    /**
     * 获取key-value,返回string
     * @param key
     * @return
     */
    public String get(String key){
        ValueOperations<String, String> operations = opsForValue();
        return operations.get(key);
    }
    /**
     * 获取key-value,返回指定类型
     * @param key
     * @return
     */
    public <T> T get(String key,Class<T> clazz){
        return JSON.parseObject(get(key),clazz);
    }
    /**
     * 获取key-value,返回指定类型的list集合
     * @param key
     * @return
     */
    public <T> List<T> getList(String key,Class<T> clazz){
        return JSON.parseArray(get(key),clazz);
    }

    /**
     * 计数器自增,默认+1
     * @param key
     */
    public void increment(String key){
        increment(key,1L);
    }

    /**
     * 计数器自增,传入自定义自增数
     * @param key
     * @param l
     */
    public void increment(String key,long l){
        ValueOperations<String, String> operations = opsForValue();
        operations.increment(key,l);
    }

    /**
     * 设置hash表键值对
     * @param tableName 表key
     * @param key 键key
     * @param obj 值value
     */
    public void hSet(String tableName,String key,Object obj){
        HashOperations<String, String, Object> operations = opsForHash();
        Object value;
        if (obj instanceof Integer || obj instanceof Long || obj instanceof String
            || obj instanceof Boolean || obj instanceof Double || obj instanceof Float){
            value = obj;
        }else {
            value = JSON.toJSONString(obj);
        }
        operations.put(tableName,key,value);
    }

    /**
     * 获取hash表键值对-值value
     * @param tableName 表key
     * @param key 键
     * @return
     */
    public Object hGet(String tableName,String key){
        HashOperations<String, String, Object> operations = opsForHash();
        return operations.get(tableName,key);
    }
    /**
     * 获取hash表键值对-值value,指定返回类型
     * @param tableName 表key
     * @param key 键
     * @return
     */
    public <T> T hGet(String tableName,String key,Class<T> clazz){
        String value = (String) hGet(tableName, key);
        return JSON.parseObject(value,clazz);
    }
    /**
     * 获取hash表键值对-值value,返回指定类型的list集合
     * @param tableName 表key
     * @param key 键
     * @return
     */
    public <T> List<T> hGetList(String tableName,String key,Class<T> clazz){
        String value = (String) hGet(tableName, key);
        return JSON.parseArray(value,clazz);
    }

    /**
     * hash表计数器自增,默认+1
     * @param tableName 表key
     * @param key 键
     */
    public void hIncrement(String tableName,String key){
        hIncrement(tableName,key,1L);
    }

    /**
     * hash表计数器自增,传入自定义自增数
     * @param tableName 表key
     * @param key 键
     * @param l
     */
    public void hIncrement(String tableName,String key,long l){
        HashOperations<String, String, Object> operations = opsForHash();
        operations.increment(tableName,key,l);
    }

    /**
     * 获取hash表所有键值对
     * @param tableName 表key
     * @return
     */
    public Map<String,Object> hEntries(String tableName){
        HashOperations<String, String, Object> operations = opsForHash();
        return operations.entries(tableName);
    }

    /**
     * 批量获取hash表键值对-值value
     * @param tableName 表key
     * @param keys 键集合
     * @return
     */
    public List<Object> hMultiGet(String tableName,List<String> keys){
        HashOperations<String, String, Object> operations = opsForHash();
        return operations.multiGet(tableName,keys);
    }

    /**
     * 删除hash表某一个键值对
     * @param tableName 表key
     * @param key 键
     * @return
     */
    public Long hDelete(String tableName,String key){
        HashOperations<String, String, Object> operations = opsForHash();
        return operations.delete(tableName,key);
    }

    /**
     * 批量删除hash表键值对
     * @param tableName 表key
     * @param keys 键集合
     * @return
     */
    public Long hDelete(String tableName,List<String> keys){
        HashOperations<String, String, Object> operations = opsForHash();
        return operations.delete(tableName,keys.toArray());
    }

    /**
     * redis锁 默认5s过期
     * @param key
     * @return
     */
    public boolean lock(String key){
        return lock(key,5);
    }

    /**
     * redis锁
     * @param key
     * @param second 秒
     * @return
     */
    public boolean lock(String key,long second){
        return setIfAbsent(key,"1",second,TimeUnit.SECONDS);
    }
}
